package com.jianguozh.difs.support.api.ops;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.jianguozh.difs.common.bean.R;
import com.jianguozh.difs.common.exception.DifsException;
import com.jianguozh.difs.framework.base.BaseController;
import com.jianguozh.difs.support.service.base.entity.Config;
import com.jianguozh.difs.support.service.base.service.IConfigService;
import com.jianguozh.difs.support.service.component.file.core.FileClientManager;
import com.jianguozh.difs.support.service.component.file.core.client.FileClientSetting;
import com.jianguozh.difs.support.service.constant.enums.ConfigTypeEnum;
import com.jianguozh.difs.support.service.constant.enums.FileStorageEnum;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件存储器配置控制器
 *
 * @author hanrs
 * @email 4076130@qq.com
 * @since 2022/7/15 14:13
 */
@RestController
@RequestMapping("/file-client-setting")
@Slf4j
public class FileClientSettingController extends BaseController {

    @Autowired
    IConfigService configService;

    @Autowired
    FileClientManager fileClientManager;

    private static final Map<String, String> fieldLableMap = new HashMap();

    static {
        fieldLableMap.put("domain", "自定义域名");
        fieldLableMap.put("endpoint", "endpoint");
        fieldLableMap.put("bucket", "桶名");
        fieldLableMap.put("accessKey", "accessKey");
        fieldLableMap.put("accessSecret", "accessSecret");
        fieldLableMap.put("basePath", "基础路径");
        fieldLableMap.put("host", "主机地址");
        fieldLableMap.put("port", "端口号");
        fieldLableMap.put("username", "用户名");
        fieldLableMap.put("password", "密码");
        fieldLableMap.put("mode", "连接模式");
    }

    @GetMapping("/file-storage")
    public R<String> getFileStorage() {
        FileClientSetting fileClientSetting = getFileClientSetting();
        return ObjectUtil.isNotNull(fileClientSetting) ? success(fileClientSetting.getFileStorage()) : success();
    }

    @GetMapping("/{fileStorage}")
    public R<List<FieldItem>> getFileClientSetting(@PathVariable String fileStorage) {
        FileStorageEnum fileStorageEnum = FileStorageEnum.valueOf(fileStorage);
        if (ObjectUtil.isNull(fileStorageEnum)) {
            return failed("无此文件存储器类型.");
        }

        FileClientSetting fileClientSetting = getFileClientSetting();
        if (ObjectUtil.isNull(fileClientSetting) || !fileStorage.equalsIgnoreCase(fileClientSetting.getFileStorage())) {
            fileClientSetting = ReflectUtil.newInstance(fileStorageEnum.getConfigClass());
        }
        List<FieldItem> fieldItems = covert(fileClientSetting);
        return success(fieldItems);
    }

    @PostMapping("/test")
    public R<String> test(@RequestBody Map<String, Object> settingMap) {
        FileClientSetting fileClientSetting = (FileClientSetting) configService.parseSetting(ConfigTypeEnum.FILE_CLIENT_CONFIG, settingMap);
        try {
            String path = fileClientManager.testFileClient(fileClientSetting);
            return success("测试成功,文件访问地址:" + path);
        } catch (Exception e) {
            throw new DifsException("文件上传测试失败.原因:" + e.getMessage());
        }
    }

    private FileClientSetting getFileClientSetting() {
        Config config = configService.getByType(ConfigTypeEnum.FILE_CLIENT_CONFIG);
        if (ObjectUtil.isNotNull(config)) {
            return (FileClientSetting) config.getSetting();
        }
        return null;
    }

    private List<FieldItem> covert(Object o) {
        List list = new ArrayList();
        Field[] fields = o.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field f = fields[i];
            boolean isStatic = Modifier.isStatic(f.getModifiers());
            if (isStatic) {
                continue;
            }
            String name = f.getName();
            String label = fieldLableMap.get(name);
            String value = (String) getFieldValue(name, o);
            FieldItem item = new FieldItem(name, label, value);
            list.add(item);
        }
        return list;
    }

    private static Object getFieldValue(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(o, new Object[]{});
            return value;
        } catch (Exception e) {
            log.error("获取属性值失败！" + e, e);
        }
        return null;
    }

    @Getter
    @Setter
    private class FieldItem {
        private String name;
        private String placeholder;
        private String label;
        private String initialValue;
        private JSONArray rules;

        public FieldItem() {
        }

        public FieldItem(String name, String label, String initialValue) {
            this.name = name;
            this.placeholder = "请输入" + label;
            this.label = label;
            this.initialValue = initialValue;
            JSONArray jsonArray = new JSONArray();
            JSONObject required = new JSONObject();
            required.putOnce("required", true);
            required.putOnce("message", label + "为必填项.");
            jsonArray.add(required);
            this.rules = jsonArray;

        }
    }

}
